import { PortfolioService, PortfolioUniversesType } from "../portfolio.service";
import { AppComponent } from "../../../app.component";
import { LrtmService, LongRunningTaskTypeEnum } from "../../../framework/lrtm/lrtm.service";
import { Component, ChangeDetectorRef } from "@angular/core";
import { PaginationPositionDisplayEnum } from "../../../shared/components/table/table.component";
import { ColumnOptions } from "../../../shared/components/table/models/columnOptions.model";
import { PortfolioAction } from "../models/portfolioAction.model";
import { TableOptions } from "../../../shared/components/table/models/tableOptions.model";
import { TableButton } from "../../../shared/components/table/models/tableButton.model";
import { StorageService } from "../../../shared/services/storage.service";
import { ActivatedRoute, Router } from "@angular/router";
import { SearchType } from "../../../shared/components/search/search.service";
import { PortfolioSharingStatus } from "../models/portfolioSharingStatus.model";
import swal, { SweetAlertOptions } from "sweetalert2";
import { UtilsService } from "../../../shared/services/utils.service";
import * as _ from 'lodash';
import { BaseComponent } from "../../../shared/components/baseComponent/base.component";
import { AnalyticsService } from "../../../shared/services/googleAnalytics.service";
import { GoogleAnalyticsBeacon } from "../../../shared/models/googleAnalytics.model";
import { PortfolioType } from "../models/portfolioType.model";
import { Observable } from "rxjs";
import { PortfolioMonitoringStatusModel } from "../models/portfolioMonitoringStatus.model";

@Component({
    templateUrl: './portfolioEdit.component.html',
    styleUrls: ['./portfolioEdit.component.scss', '../../../../assets/table.scss'],
    providers: [PortfolioService]
})
export class PortfolioEditComponent extends BaseComponent {
    constructor(
        private rootComponent: AppComponent,
        private portfolioService: PortfolioService,
        private route: ActivatedRoute,
        private router: Router,
        private lrtmService: LrtmService,
        private cdRef: ChangeDetectorRef,
        private analyticsService: AnalyticsService) {
        super(cdRef);
    }

    public securitiesSource: any[];
    public paginationPosition = PaginationPositionDisplayEnum.Down;
    public searchTypeCompany: SearchType = SearchType.company;
    public securitiesCount: number;
    public filter: any;
    public portfolioId: string;
    public portfolio: any;
    public portfolioShared: any;
    
    public newPortfolioName: string;
    public currentPortfolioName: string;
    public editButtonIsVisible: boolean;
    public portfolioNameEditIsVisible: boolean;

    public hasAnalyticsClaim: boolean = false;
    public portfolioList: any[];
    public benchmarkList: any[];
    public exagoReportNameList: any[] = [];
    public exagoReportName: string;
    public firstSelection: string;
    public secondSelection: string = 'null';
    public exagoUrl: string = undefined;

    private userId: string;
    private accountId: string;
    private canEditPortfolio: boolean;

    public hasMonitoringClaim: boolean;
    public portfolioMonitored: boolean;
    public monitorAllChecked: boolean = false;

    public monitoringStatus: PortfolioMonitoringStatusModel;

    public securitiesColumns: ColumnOptions[] = [
        new ColumnOptions('MatchedCompanyName', 'MatchedCompanyName', 'Matched Company Name & ID', 'w-20 px-2', false, undefined, false, null, false, false, false, true, undefined, true),
        new ColumnOptions('SecurityWeight', 'SecurityWeight', 'Security Weight', 'w-15 text-right pr-4 pl-1', false, undefined, false, null, false, false, false, true, undefined, false, true),
        new ColumnOptions('SecurityName', 'SecurityName', 'Security Name & ID', 'w-20 px-2', false, undefined, false, null, false, false, false, true, undefined, true),
        new ColumnOptions('Exchange', 'Exchange', 'Exchange', 'w-10 px-2', false, undefined, false, null, false, false, false, true),
        new ColumnOptions('Subindustry', 'Subindustry', 'Subindustry', 'w-25 pr-3', false, undefined, false, null, false, false, false, true),
        new ColumnOptions('Actions', 'Actions', '', 'w-10', false, undefined, false, null, false, false, true, true)
    ];

    ngOnInit() {
        let userInfo = StorageService.get().userInfo;
        this.userId = userInfo.userId;
        this.accountId = userInfo.accountId;
        this.hasMonitoringClaim = this.hasPermission('api/v1/subscribetoportfolio', 'PUT', [{ key: 'alert', value: 'quarterly' }]);


        this.route.params.subscribe(param => {
            this.portfolioId = param['id'];
            this.firstSelection = this.portfolioId;
            this.editButtonIsVisible = true;
            this.portfolioNameEditIsVisible = false;
            this.getPortfolioDetails();
            if (this.hasMonitoringClaim)
                this.getMonitoringStatus();
            this.rootComponent.finishLoading();
        });

        this.hasAnalyticsClaim = this.hasPermission('api/v1/portfolios', 'GET', [{ key: 'shortName', value: 'portfolioanalytics' }]);
        if (this.hasAnalyticsClaim) {
            //TODO:in the future, cache result of getPortfolioMonitoring, but parameter is different
            let privatePort = this.portfolioService.getPortfolio(0, 0, 'NameLowercase', true, PortfolioSharingStatus.All, PortfolioType.Custom);
            let sharedPort = this.portfolioService.getPortfolio(0, 0, 'NameLowercase', true, PortfolioSharingStatus.Shared, PortfolioType.Custom);
            let systemPort = this.portfolioService.getPortfolio(0, 0, 'NameLowercase', true, PortfolioSharingStatus.All, PortfolioType.System);

            Observable.forkJoin([privatePort, sharedPort, systemPort]).subscribe(data => {
                this.portfolioList = [
                    { type: PortfolioUniversesType["My portfolios"], name: "My portfolios", children: data[0] },
                    { type: PortfolioUniversesType["Shared portfolios"], name: "Shared portfolios", children: data[1] }
                ]

                this.benchmarkList = this.portfolioList.concat([{ type: PortfolioUniversesType["System portfolios"], name: "System portfolios", children: data[2] }]);
            });
            let i = 0;
            this.portfolioService.getExagoReportNames().subscribe(data => {
                data.forEach(element => {
                    let reportPath = element.toString();
                    this.exagoReportNameList.push({ path: reportPath, name: reportPath.substring(reportPath.lastIndexOf("//") + 2) });
                });
            });
        }
    }

    private setColumns() {
        this.securitiesColumns = [
            new ColumnOptions('MatchedCompanyName', 'MatchedCompanyName', 'Matched Company', 'w-20 px-2', false, undefined, false, null, false, false, false, true, undefined, true),
            new ColumnOptions('SecurityWeight', 'SecurityWeight', 'Security Weight', 'w-15 text-right pr-4 pl-1', false, undefined, false, null, false, false, false, true, undefined, false, this.canEditPortfolio),
            new ColumnOptions('SecurityName', 'SecurityName', 'Security Name & ID', 'w-20 px-2', false, undefined, false, null, false, false, false, true, undefined, true),
            new ColumnOptions('Exchange', 'Exchange', 'Exchange', 'w-10 px-2', false, undefined, false, null, false, false, false, true, undefined, false, false, true),
            new ColumnOptions('Subindustry', 'Subindustry', 'Subindustry', 'w-25 pr-3', false, undefined, false, null, false, false, false, true, undefined, false, false, true),
            new ColumnOptions('Actions', 'Actions', '', 'w-10', false, undefined, false, null, false, false, true, true)
        ];
    }

    private getSecuritiesPortfolios(skip: number, take: number) {
        this.portfolioService.getPortfolioDetails(this.portfolioId, skip, take, "CompanyNameLowercase", true).subscribe(
            data => {
                let companiesAdditionalDetails = data.portfolioAdditionalDetails;
                let securities = data.portfolioDetails.map(security => {
                    const buttons = [
                        new TableButton("Remove", {
                            action: PortfolioAction.Delete,
                            securityId: security.id
                        },
                            this.canEditPortfolio
                        )
                    ];

                    return {
                        matchedCompanyName: { FirstLine: security.matchedInfo.capitalIQId, SecondLine: security.matchedInfo.companyName },
                        securityWeight: { value: security.securityWeight, action: PortfolioAction.UpdatePortfolioWeight, securityId: security.id, isEdit: false },
                        securityName: { FirstLine: security.displayInfo.securityIdentifier, SecondLine: security.displayInfo.customSecurityIdentifierName }, //security.displayInfo.customSecurityIdentifierName + ' ' + security.displayInfo.securityIdentifier,
                        exchange: companiesAdditionalDetails.filter(x => x.id == security.companyId)[0].exchange,
                        subindustry: companiesAdditionalDetails.filter(x => x.id == security.companyId)[0].subindustry,
                        actions: this.canEditPortfolio ? buttons : []
                    };
                });

                this.securitiesSource = securities;
                this.securitiesCount = data.portfolioCompanyCount;
            }
        );
    }

    public addCompanyToPortfolio(companyIdToAdd: string) {
        this.portfolioService.addCompanyToPortfolio(companyIdToAdd, this.portfolio.id)
            .subscribe(result => {
                if (result && result.indexOf("5103") != -1) {
                    this.rootComponent.showSuccess('The company added to the selected portfolio successfully');
                    this.rootComponent.showWarning('The company already exists in the selected portfolio');
                } else {
                    this.rootComponent.showSuccess('The company added to the selected portfolio successfully');
                }
                this.getSecuritiesPortfolios(0, 20);
            });
    }

    private getPortfolioDetails() {
        this.portfolioService.getPortfolioById(this.portfolioId).subscribe(data => {
            this.portfolio = data;
            this.canEditPortfolio = this.portfolio.isMyPortfolio;
            this.portfolioShared = this.portfolio.sharingStatus == 2 ? true : false;
            this.newPortfolioName = this.portfolio.name;
            this.currentPortfolioName = this.portfolio.name;
            this.setColumns();
            this.getSecuritiesPortfolios(0, 20);
        });
    }

    private deleteCompanyFromPortfolio(securityId: string) {
        const swalOptions: SweetAlertOptions = Object.assign(UtilsService.getBaseSwalOptions(), {
            title: 'Remove Security',
            text: 'Are you sure you want to remove this security?',
            confirmButtonClass: 'btn btn-danger',
            confirmButtonText: 'Remove',
            imageUrl: '/assets/icons-svg/icon-warning.svg'
        });
        swal(swalOptions).then(result => {
            if (result && result.value === true) {
                this.portfolioService
                    .deleteCompanyFromPortfolio(this.portfolioId, securityId)
                    .subscribe(() => {
                        this.rootComponent.showSuccess("Security successfully deleted from the portfolio.", "Success")
                        this.getSecuritiesPortfolios(0, 20);
                    });
            }
        });
    }

    public onButtonClicked(actionOptions: any): void {
        switch (actionOptions.action) {
            case PortfolioAction.Delete:
                this.deleteCompanyFromPortfolio(actionOptions.securityId);
                break;
            case PortfolioAction.UpdatePortfolioWeight:
                this.updatePortfolioWeight(actionOptions);
                break;
        }
    }

    private updatePortfolioWeight(updateParams: any) {
        if (isNaN(updateParams.value)) {
            this.rootComponent.showError("'" + updateParams.value + "' is not a number. Please write a valid number!");
            return;
        }
        this.portfolioService
            .updatePortfolioWeight(this.portfolioId, updateParams.securityId, updateParams.value, updateParams.value == '' ? true : false)
            .subscribe(_ => {
                this.rootComponent.showSuccess("Security weight updated.", "Success");
            });
    }

    public tableOptionsChangedSecurities(tableOptions: TableOptions): void {
        this.getSecuritiesPortfolios(tableOptions.pageOptions.skip, tableOptions.pageOptions.take);
    }

    public changeName() {
        if (this.newPortfolioName == this.portfolio.name) {
            this.rootComponent.showError("Please write a different name.");
            return;
        }
        if (!this.newPortfolioName || this.newPortfolioName.trim() === '') {
            this.rootComponent.showError("Please write a name.");
            return;
        }

        this.portfolioService.updatePortfolioName(this.portfolioId, this.newPortfolioName).subscribe(() => { });
        this.editButtonIsVisible = true;
        this.portfolioNameEditIsVisible = false;
        this.currentPortfolioName = this.newPortfolioName;
        this.rootComponent.showSuccess("Portfolio name successfully updated.", "Success");
    }

    public changePortfolioSharingStatus() {
        let status = !this.portfolioShared == true ? PortfolioSharingStatus.Private : PortfolioSharingStatus.Shared;
        this.portfolioService.updatePortfolioStatus(this.portfolioId, status.toString()).subscribe(() => {
            this.rootComponent.showSuccess("Portfolio status successfully updated.", "Success");
        });
    }

    private getMonitoringStatus() {
        this.portfolioService.getPortfolioMonitoring(this.userId, this.accountId).subscribe(response => {
            this.monitoringStatus = response;
            this.portfolioMonitored = this.monitoringStatus.portfoliosMonitoredIds.some( x=> x == this.portfolioId);
            this.monitorAllChecked = this.monitoringStatus.isMonitoringAll;
        });
    }

    public changePortfolioMonitoredStatus() {
        let portfolioInfo = {
            portfolio : { id: this.portfolioId},
            isChecked: this.portfolioMonitored
        };
        this.portfolioService.modifyPortfolioSubscription(portfolioInfo, this.monitoringStatus, this.userId, this.accountId).subscribe(
            response => {
                if(response != null) this.rootComponent.showSuccess(response.message, "Success!"); 
            }
        )
    }

    public deletePortfolio() {
        this.portfolioService.deletePortfolio(this.portfolioId).subscribe(response => {
            this.rootComponent.showSuccess("Portfolio successfully deleted.", "Success");
            this.router.navigate(['../../'], { relativeTo: this.route });
        });
    }

    public exportPortfolio() {
        var data = {
            id: this.portfolioId,
            accountId: this.accountId,
            userId: this.userId,
            name: this.portfolio.name
        };
        var date = UtilsService.getReportDate();
        this.analyticsService.sendBeacon(new GoogleAnalyticsBeacon('ExcelPortfolioExport', 'Portfolio Management', { PortfolioId: this.portfolioId }));
        this.lrtmService.runTask(this.rootComponent, 'Portfolio_' + this.portfolio.name + '_' + date, LongRunningTaskTypeEnum.PortfolioExportExcel, data, true, null).subscribe(data => {
        });
    }

    public selectPortfolio(target: any, isFirst: boolean) {
        if (isFirst)
            this.firstSelection = target.value;
        else
            this.secondSelection = target.value;
        this.exagoUrl = undefined;
    }

    public selectReport(target: any) {
        this.exagoReportName = target.value;
        this.exagoUrl = undefined;
    }

    public generate() {
        this.analyticsService.sendBeacon(new GoogleAnalyticsBeacon('PortfolioReporting', 'Portfolio Management', { PortfolioId: this.firstSelection, BenchmarkId: this.secondSelection }));
        this.portfolioService.generatePortfolioAnalytics(this.firstSelection, this.secondSelection,this.accountId, this.exagoReportName).subscribe(data => {
            this.exagoUrl = data;
        }, error => {
            this.rootComponent.showWarning(error.error.message);
        });
    }

}